package com.pig4cloud.pig.model.controller;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.Gson;
import com.pig4cloud.pig.common.security.annotation.Inner;
import com.pig4cloud.pig.model.api.dto.ModelDTO;
import com.pig4cloud.pig.model.api.entity.ManagementEntity;
import com.pig4cloud.pig.model.api.entity.ModelServiceEntity;
import com.pig4cloud.pig.model.service.ManagementService;
import com.pig4cloud.pig.model.service.ModelServiceService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import okhttp3.ConnectionPool;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.apache.commons.compress.utils.Lists;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.net.URISyntaxException;
import java.util.Enumeration;

import org.springframework.http.MediaType;
import java.io.IOException;
import java.net.URI;
import java.util.Collections;
import java.util.List;

import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.HttpClients;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;

/**
 * @Author: marco
 * @Date: 2024-06-17 17:32
 * @Desperation: TODO
 */
@Tag(description = "proxy" , name = "代理请求" )
@RestController
@RequestMapping("/proxy")
@Slf4j
@RequiredArgsConstructor
@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
public class Proxy1Controller {
	private final ManagementService managementService;
	private final ModelServiceService modelServiceService;


	@Inner(value = false)
	@Operation(summary = "get请求接口转发" , description = "接口转发" )
	@GetMapping("/resolve/**")
	public String handle(HttpServletRequest request) throws IOException, URISyntaxException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
		HttpHeaders headers = getRequestHeaders(request);
		ManagementEntity managementEntity=managementService.getById(headers.get("model_id").get(0));
		ModelServiceEntity modelServiceEntity = modelServiceService.getById(managementEntity.getServiceId());
		URI targetUri = new URI(modelServiceEntity.getProtocol()+"://"+modelServiceEntity.getHost() +":"+modelServiceEntity.getPort()+modelServiceEntity.getPath()+ managementEntity.getUrl());
		String method = managementEntity.getMethod();
		System.out.println(targetUri);
		HttpEntity<?> entity = new HttpEntity<>(headers);
		RestTemplate restTemplate = new RestTemplate(getSecureHttpRequestFactory());
		String testMethod = request.getMethod();
		String params;
		if (testMethod.equalsIgnoreCase(HttpMethod.GET.name())) {
			params = request.getQueryString();
			ResponseEntity<String> responseEntity=restTemplate.exchange(targetUri+"?"+params, HttpMethod.resolve(method), entity, String.class);
			return responseEntity.getBody();
		} else if (testMethod.equalsIgnoreCase(HttpMethod.POST.name())) {
			params = getRequestBody(request);
			System.out.println(params);
			headers.setContentType(MediaType.APPLICATION_JSON);
			HttpEntity<String> postEntity = new HttpEntity<>(params, headers);
			ResponseEntity<String> responseEntity=restTemplate.exchange(targetUri, HttpMethod.resolve(method), postEntity, String.class);
			return responseEntity.getBody();
		} else {
			return "Unsupported request method:" + method;
		}

	}

	@Inner(value = false)
	@Operation(summary = "post请求接口转发" , description = "接口转发" )
	@PostMapping("/resolve/**")
	public String handleRequest(@RequestBody ModelDTO  modelDTO, HttpServletRequest request) throws IOException, URISyntaxException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
		HttpHeaders headers = getRequestHeaders(request);
		ManagementEntity managementEntity=managementService.getById(headers.get("model_id").get(0));
		ModelServiceEntity modelServiceEntity = modelServiceService.getById(managementEntity.getServiceId());
		URI targetUri = new URI(modelServiceEntity.getProtocol()+"://"+modelServiceEntity.getHost() +":"+modelServiceEntity.getPort()+ managementEntity.getUrl());
		String method = managementEntity.getMethod();
		System.out.println(targetUri);
		HttpEntity<?> entity = new HttpEntity<>(headers);
		RestTemplate restTemplate = new RestTemplate(getSecureHttpRequestFactory());
		String testMethod = request.getMethod();
		String params = "";
		if (testMethod.equalsIgnoreCase(HttpMethod.GET.name())) {
			params = request.getQueryString();
			ResponseEntity<String> responseEntity=restTemplate.exchange(targetUri+"?"+params, HttpMethod.resolve(method), entity, String.class);
			return responseEntity.getBody();
		} else if (testMethod.equalsIgnoreCase(HttpMethod.POST.name())) {
			params= new Gson().toJson(modelDTO);
			System.out.println(params);
			headers.setContentType(MediaType.APPLICATION_JSON);
			HttpEntity<String> postEntity = new HttpEntity<>(params, headers);
			ResponseEntity<String> responseEntity=restTemplate.exchange(targetUri, HttpMethod.resolve(method), postEntity, String.class);
			return responseEntity.getBody();
		} else {
			return "Unsupported request method:" + method;
		}

	}

	private HttpHeaders getRequestHeaders(HttpServletRequest request) {
		HttpHeaders headers = new HttpHeaders();
		Enumeration<String> headerNames = request.getHeaderNames();
		while (headerNames.hasMoreElements()) {
			String headerName = headerNames.nextElement();
			List<String> headerValues = Collections.list(request.getHeaders(headerName));
			headers.put(headerName, headerValues);
		}
		return headers;
	}

	private String getRequestBody(HttpServletRequest request) throws IOException {
		StringBuilder jsonBuilder = new StringBuilder();
		String line;
		BufferedReader reader = request.getReader();
		while ((line = reader.readLine()) != null) {
			jsonBuilder.append(line);
		}
		return request.getReader().lines().reduce("", (accumulator, actual) -> accumulator + actual);
	}

	private HttpComponentsClientHttpRequestFactory getSecureHttpRequestFactory() throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
		TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
			@Override
			public X509Certificate[] getAcceptedIssuers() {
				return null;
			}

			@Override
			public void checkClientTrusted(X509Certificate[] certs, String authType) {
			}

			@Override
			public void checkServerTrusted(X509Certificate[] certs, String authType) throws CertificateException {
			}
		} };

		SSLContext sslContext = SSLContext.getInstance("TLS");
		sslContext.init(null, trustAllCerts, null);

		SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);

		HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
		requestFactory.setHttpClient(HttpClients.custom().setSSLSocketFactory(csf).build());

		return requestFactory;
	}

//	public static void main(String[] args) {
//		JSONObject arrObj=new JSONObject();
//		arrObj.put("count",3);
//		arrObj.put("tt",240);
//		List<Double> list= Lists.newArrayList();
//		list.add(0.0);
//		list.add(61.54281525);
//		list.add(284.1946847);
//		arrObj.put("q",list);
//		List<Double> list2= Lists.newArrayList();
//		list2.add(23.4);
//		list2.add(0.72);
//		list2.add(2.88);
//		arrObj.put("dq",list2);
//		System.out.println("输入参数："+arrObj);
//		okhttp3.MediaType mediaType = okhttp3.MediaType.parse("application/json");
//		okhttp3.RequestBody body = okhttp3.RequestBody.create(mediaType, arrObj.toString());
//		Request request = new Request.Builder()
//				.url("http://127.0.0.1:9999/model/proxy/resolve/psjs/PostByJson")
//				.method("POST", body)
//				.addHeader("Content-Type", "application/json")
//				.addHeader("model_id", "1802888332705214465")
//				.build();
//		String result="";
//		try {
//			OkHttpClient HTTP_CLIENT = new OkHttpClient().newBuilder().connectTimeout(10, TimeUnit.SECONDS).connectionPool(new ConnectionPool(5,4,TimeUnit.SECONDS)).build();
//			Response response =HTTP_CLIENT.newCall(request).execute();;
//			String str=response.body().string();
//			JSONObject pa = JSONObject.parseObject(str);
//			System.out.println(pa.toJSONString());
//			String choices=pa.getString("data");
//			JSONObject objects = JSONObject.parseObject(choices);
//			if(objects!=null){
//				String message=objects.getString("token");
//				System.out.println(message);
//				result=message;
//			}
//		} catch (IOException e) {
//			e.printStackTrace();
//		}
//	}
}

